package logo.sys;

import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

@SuppressWarnings("serial")
public class TurtleDisplay extends JPanel {
    /** Object for displaying lines drawn by a Logo Turtle **/

    /**
       Virtual coordinates of extreme points of the display
	Coordinates are in the range [-100,100].
    **/

    double left = -200F;
    double bottom = -200F;
    double right = 200F;
    double top = 200F;
    
    double xscale, yscale;	// scale factors to convert coords to pixels
    int ymax;			// max pixel y coordinate

    /** xscale, yscale, ymax must be updated automatically if the window
	is resized **/
    /* need to catch an AWTEvent (ComponentEvent) to resize them properly */

    Container myContainer;	// container for this display

    static Color foregroundColour;
    static Color backgroundColour = Color.white;
    static Color turtleColour = Color.black;

    Image myImage;		// off-screen contents of this display
    Image turtleImage;		// current image of turtle

    Shape turtleShape;
    AffineTransform turtleXform;
    final int TURTLE_WIDTH = 16;
    final int TURTLE_HEIGHT = 16;

    /** Create a new TurtleDisplay object with given width
	and height **/
    public TurtleDisplay(){
	super();

	//setSize(Turtle.CANVAS_SIZE, Turtle.CANVAS_SIZE);
	setVisible(true);

	init(TURTLE_WIDTH, TURTLE_HEIGHT);
	setForeground(0, 0, 200);
	setBackground(Color.yellow);
	setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
    }

    /** Create the default turtle shape with the given dimensions */
    public void init(int width, int height)
    {
	//setIcon(new ImageIcon(myImage));

	/* Use a triangle as default turtle */
	int[] xs = {0, width/2, width, width/2};
	int[] ys = {0, height, 0, height/3};
	turtleShape = new Polygon(xs, ys, 4);
    }

    public Image makeTurtleImg(Shape turtleShape, int width, int height) {
	Image result = createImage(width, height);
	if (result == null) {
	    System.out.println("Failed to create turtle");
	    return result;
	}
	Graphics2D g2 = (Graphics2D)result.getGraphics();
	g2.setColor(turtleColour);
	// should probably make background transparent
	g2.draw(turtleShape);
	return result;
    }
    
    public static Frame makeDefaultFrame(int width, int height) {
	Frame result = new Frame();
	result.setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));
	result.setSize(width, height);
	result.setBackground(Color.cyan);

	return result;
    }

    /** Show the turtle at the specified coordinates with the given bearing. */
    public void showTurtle(double bearing, double x, double y) {
	if (turtleImage == null)
	    rescale(getWidth(), getHeight());
	int tx = convertX(x);
	int ty = convertY(y);
	int tcx = TURTLE_WIDTH/2; // centre of turtle
	int tcy = TURTLE_HEIGHT/2; // centre of turtle
	turtleXform = AffineTransform.getTranslateInstance(tx, ty);
	turtleXform.rotate(bearing);
	turtleXform.scale(1D, -1D);
	turtleXform.translate(-tcx, -tcy);
	//getGraphics().drawImage(myImage, 0, 0, this);
	repaint();
    }

    /** Do not show the turtle. */
    public void hideTurtle() {
	turtleXform = null;
	repaint();
    }

    /** Set the size of this display */
    public void setSize(int width, int height) {
	super.setSize(width, height);
	// invalidate images
	// should probably save current image to be copied to new one
	myImage = null;
	turtleImage = null;
	rescale(width, height);
    }

    public void rescale(int width, int height) {
	xscale = (width - 1)/(right - left);
	yscale = (height - 1)/(top - bottom);
	ymax = height - 1;
	myImage = createImage(width, height);
	turtleImage = makeTurtleImg(turtleShape, TURTLE_WIDTH, TURTLE_HEIGHT);
    }
    
    public void paintComponent(Graphics g) {
	super.paintComponent(g);
	Graphics2D g2 = (Graphics2D) g;
	//g2.clearRect(0, 0, getWidth(), getHeight());
	//g2.setColor(Color.green);

	if (myImage == null)
	    rescale(getWidth(), getHeight());

	if (myImage != null)
	    g2.drawImage(myImage, 0, 0, backgroundColour, this);

	g2.setColor(turtleColour);
	if (turtleXform != null) {
		g2.transform(turtleXform);
		g2.draw(turtleShape);
	}

// 	if (turtleImage == null)
// 	    rescale(getWidth(), getHeight());

// 	if ((turtleImage != null) && (turtleXform != null))
// 	    g2.drawImage(turtleImage, turtleXform, this);
    }

    public void clear() {
	Dimension dims = getSize();
	myImage.getGraphics().clearRect(0,0, dims.width, dims.height);
	repaint();
    }
    
    protected int convertX(double x) {
	/** Convert the given x coordinate to pixel coordinate **/
	return (int)((x - left) * xscale);
    }

    protected int convertY(double y) {
	/** Convert the given y coordinate to pixel coordinate **/
	return (int)(ymax - ((y - bottom) * yscale));
    }
    
    protected void setCoordinateLimits(double minX, double minY,
				       double maxX, double maxY) {
	left = minX;
	bottom = minY;
	right = maxX;
	top = maxY;
	xscale = (getSize().width - 1)/(right - left);
	yscale = (getSize().height - 1)/(top - bottom);
    }

    public void setForeground(int r, int g, int b) {
	Color c = new Color(r,g,b);
	foregroundColour = c;
    }

    public void setForeground(Color c) {
	foregroundColour = c;
    }
    
    public void setBackground(int r, int g, int b) {
	Color c = new Color(r, g, b);
	backgroundColour = c;
    }

    public void drawSegment(double x,double y , double x1, double y1) {

	if (myImage == null)
	    rescale(getWidth(), getHeight());

	if (myImage == null) {
	    System.out.println("Image is null, so cannot draw line");
	    return;
	}

	int startX = convertX(x);
	int startY = convertY(y);
	int endX = convertX(x1);
	int endY = convertY(y1);
	
	Graphics2D g2 = (Graphics2D) myImage.getGraphics();
	g2.setColor(foregroundColour);
	g2.drawLine(startX, startY, endX, endY);
	repaint();
    }

}
